package com.gitee.aurora.utils;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/webSocket/{deviceId}")
@Component
public class WebSocketServer {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class);

    /**
     * 存放每个客户端对应的MyWebSocket对象
     */
    private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 连接建立成功调用的方法
     * */
    @OnOpen
    public void onOpen(Session session,@PathParam(value = "deviceId") String deviceId) {
        System.out.println("服务端接收信息-------------------------");
        this.session = session;
       //判断当前设备是否已有web socket连接，有则删除
        deleteWebsocketExisted(deviceId);
       //保存当前websocket连接
        webSocketMap.put(deviceId, this);

       // 通知客户端建立连接成功
        sendMessage(deviceId + "connected success");

       //设备状态变化(设备连接成功通知)
        statusChange(deviceId, true);
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * */
    @OnMessage
    public void onMessage(String message) {
        System.out.println(message);

        if("ping".equals(message)){
// 心跳
            sendMessage(message);
        }else{
// 省略业务消息处理步骤
// 返回消息给客户端
            sendMessage("some message");
        }
    }

    /**
     * 连接关闭调用的方法
     * */
    @OnClose
    public void onClose() {
        String deviceId =  getKey(webSocketMap, this);
// 从set中删除
        webSocketMap.remove(deviceId);
//设备下线
        statusChange(deviceId, false);
    }

    /**
     * 发生错误时调用
     * */
    @OnError
    public void onError(Throwable error) {
        logger.error("Error:"+error.getMessage());
    }

    private void statusChange(String deviceId, boolean status) {
        if (status) {
            logger.info("设备{}上线", deviceId);
        }else{
            logger.info("设备{}下线", deviceId);
        }
// 省略操作数据库步骤
    }


    private void deleteWebsocketExisted(String deviceId) {
        WebSocketServer oldConnection = webSocketMap.get(deviceId);
        if(null != oldConnection){
            try {
                oldConnection.getSession().close();
            } catch (IOException e) {
                logger.error("IOException:{}"+e.getMessage());
            }
        }
    }

    /**
     * 根据map的value获取map的key
     * @param map
     * @param myWebSocket
     * @return
     */
    private static String getKey(Map<String,WebSocketServer> map, WebSocketServer myWebSocket){
        String key="";
        for (Map.Entry<String, WebSocketServer> entry : map.entrySet()) {
            if(myWebSocket.equals(entry.getValue())){
                key=entry.getKey();
            }
        }
        return key;
    }

    public void sendMessage(String message) {
        this.session.getAsyncRemote().sendText(message);
    }

    public Session getSession() {
        return session;
    }

}
